#pragma once
#include <string>
#include <memory>
#include <functional>
#include <unordered_map>
#include <iostream>
#include <fcntl.h>
#include <sstream>
#include "eventloop.hpp"
#include "epoll_intf.hpp"
#include "../common/nocopy.hpp"
#include "../common/mysocket.hpp"

class Link;
class LinkManager; // 类的前向声明！！！

using linkcb_func = std::function<void(std::shared_ptr<Link>)>;
static const char *TAB8 = "        ";

class Link
{
    friend class LinkManager;
    std::string _inbuf;
    std::string _outbuf;

public:
    std::shared_ptr<Socket> _socket_sptr;
    uint32_t _event;
    linkcb_func _recv_cb;
    linkcb_func _send_cb;
    linkcb_func _except_cb;
    LinkManager &_linkmng;

    Link(std::shared_ptr<Socket> socket_sptr, uint32_t event, LinkManager &linkmng)
        : _socket_sptr(socket_sptr), _event(event), _linkmng(linkmng)
    {
        if (event & EPOLLET)
        {
            SetNonBlock(_socket_sptr->Fd()); // 在ET模式下必须确保fd是非阻塞的
        }
    }

    void SetNonBlock(int sockfd)
    {
        int fl = fcntl(sockfd, F_GETFL);
        if (fl == -1)
        {
            LogMessage(ERROR, "fcntl error! fd: %d", sockfd);
            exit(errno);
        }
        int ret = fcntl(sockfd, F_SETFL, fl | O_NONBLOCK);
        if (ret == -1)
        {
            LogMessage(ERROR, "fcntl error! fd: %d", sockfd);
            exit(errno);
        }
        LogMessage(DEBUG, "set nonblock success! fd %d", sockfd);
    }

    void SetCallBack(linkcb_func recv_cb, linkcb_func send_cb, linkcb_func except_cb)
    {
        _recv_cb = recv_cb;
        _send_cb = send_cb;
        _except_cb = except_cb;
    }

    void ModEvent(uint32_t event); // 成员函数的类内声明

    void AppendInbuf(const std::string &content)
    {
        _inbuf += content;
    }

    void AppendOutbuf(const std::string &content)
    {
        _outbuf += content;
    }

    std::string &GetInbuf()
    {
        return _inbuf;
    }

    std::string &GetOutbuf()
    {
        return _outbuf;
    }
};

class LinkManager
{
    friend class Link;

    std::unordered_map<int, std::shared_ptr<Link>> _linkMap;
    Epoller &_epoller;

public:
    LinkManager(Epoller &epoller)
        : _epoller(epoller)
    {
    }

    bool CheckLink(int fd)
    {
        if (_linkMap.find(fd) != _linkMap.end())
            return true;
        else
            return false;
    }

    void Connect(std::shared_ptr<Link> link_ptr)
    {
        int sockfd = link_ptr->_socket_sptr->Fd();
        _epoller.EpollCtrl(EPOLL_CTL_ADD, sockfd, link_ptr->_event);
        _linkMap.insert(make_pair(sockfd, link_ptr));
    }

    void DisConnect(std::shared_ptr<Link> link_ptr)
    {
        int sockfd = link_ptr->_socket_sptr->Fd();
        if (!CheckLink(sockfd))
            return;
        _epoller.EpollCtrl(EPOLL_CTL_DEL, sockfd, NONEVENT); // 要在close之前调用epoll_ctl删除事件
        _linkMap.erase(sockfd);
        close(sockfd);
        link_ptr->_socket_sptr->ModFd(-1); // 将链接置为无效
    }

    std::shared_ptr<Link> GetLink(int sockfd)
    {
        return _linkMap[sockfd];
    }

    void PrintLinks()
    {
        // 打印一下ip:port, sockfd, recv_q, send_q（读写缓冲区size）
        std::cout << "Foreign Address" << TAB8 << "Sockfd" << TAB8 << "Recv_Q" << TAB8 << "Send_Q" << std::endl;
        for (auto [sockfd, link_ptr] : _linkMap)
        {
            // std::cout << link_ptr->_ip << ":" << link_ptr->_port << TAB << link_ptr->_sockfd << TAB
            //           << link_ptr->_inbuf.size() << TAB << link_ptr->_outbuf.size();
            std::stringstream sstream;
            sstream << link_ptr->_socket_sptr->Fip() << ":" << link_ptr->_socket_sptr->Fport();
            // std::cout << link_ptr->_ip << std::endl;
            printf("%-21s  %-6d%s%-6ld%s%-6ld\n", sstream.str().c_str(),
                   link_ptr->_socket_sptr->Fd(), TAB8, link_ptr->_inbuf.size(), TAB8, link_ptr->_outbuf.size());
        }
        std::cout << std::endl;
    }
};

void Link::ModEvent(uint32_t event)
{
    _linkmng._epoller.EpollCtrl(EPOLL_CTL_MOD, _socket_sptr->Fd(), event);
    _event = event;
}
